using System;
using CommonBehaviors.Actions;
using FarmerJoe.Helpers;
using FarmerJoe.Helpers.Logging;
using FarmerJoe.Helpers.Units;
using FarmerJoe.Settings;
using Styx;
using Styx.CommonBot;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Action = Styx.TreeSharp.Action;

namespace FarmerJoe.Classes
{
    public static partial class Warlock
    {

        public static bool SoulFireWithMoltenCore
        {
            get
            {
                if (!Me.HasAura("Molten Core")) return false;
                if (Me.IsCasting && Me.CastingSpell.Name == "Soul Fire" && Me.Auras["Molten Core"].StackCount == 1) return false;
                if (Me.Auras["Molten Core"].StackCount >= 1) return true;

                return false;
            }
        }


        public static Composite CombatBehavior_Demonology
        {
            get
            {
                return new PrioritySelector(

                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),

                    SummonPet(),
                    PetSpells(),

                    AllFormsHeal(),
                    //new Common.NeedToUseLifeSpirit(new Common.UseLifeSpirit()),
                    Common.UseHealthManaRegenAgent(ClassParser.HealthPotion, ClassParser.ManaPotion),

                    Inventory.UseTrinket1(),
                    Inventory.UseTrinket2(),

                    Movement.MoveToLOS(),
                    Movement.FaceTarget(),
                    Movement.ForceFacingTarget(),
                    Pets.DefendMe(),
                    Movement.Fixes(),

                    // Somehow we've got a target that is not hostile or attackable. Blacklist it and move on
                    new Decorator(ret => !CT.Attackable || CT.IsFriendly,
                        new Sequence(
                            new Action(context => Log.Write(Colours.InformativeColour, "Somehow we've got a target that is friendly or not attackable, blacklisting it and moving on.")),
                            new Action(context => Blacklist.Add(CT, TimeSpan.FromMinutes(1))),
                            new Action(context => Me.ClearTarget())
                        )),

                    // Combat rotation goes here
                    Spells.Cast("Mortal Coil", ret => Me.HealthPercent <= FpswareSettings.Instance.Warlock.DemoMortalCoilHealth),

                    // Check for casting Soul Fire when the buff is not up. 
                    new Decorator(ret=> Me.IsCasting && Me.CastingSpell.Name == "Soul Fire" && !Me.HasAura("Molten Core"),
                        new Sequence(
                            new Action(delegate { SpellManager.StopCasting(); }),
                            new ActionAlwaysFail()
                        )),

                    // Protect ourself from spells if we can
                    new Decorator(ret => !FpswareSettings.Instance.Warlock.DemoTwilightWard.Contains("never") && Me.GotTarget && CT.IsCasting && CT.CastingSpell.CastTime > 1000 && CT.CurrentTarget.Guid == Me.Guid,
                            new PrioritySelector(
                                Spells.Cast("Twilight Ward", ret => CT.CastingSpell.School == WoWSpellSchool.Shadow || CT.CastingSpell.School == WoWSpellSchool.Holy)
                                )),


                    Spells.Cast("Grimoire: " + FpswareSettings.Instance.Warlock.DemoGrimoirePet, ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.DemoGrimoireOfService)),
                    Spells.Cast("Dark Soul", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.DemoDarkSoul) && !WoWSpell.FromId(113861).Cooldown && !Me.HasAura("Dark Soul: Knowledge")),
                    Spells.Cast("Grimoire of Sacrifice", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.DemoGrimoireOfSacrifice) && Me.GotAlivePet && !Me.HasAura("Grimoire of Sacrifice")),
                    Spells.Cast("Curse of the Elements", ret => !FpswareSettings.Instance.Warlock.DemoCurseOfTheElements.Contains("never") && !CT.HasAura("Aura of the Elements") && (CT.AuraTimeLeft("Curse of the Elements") < 3) && IsCastingOK),
                    Spells.Buff("Corruption", ret => Me.CurrentTarget, ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.DemoCorruption) && CT.AuraTimeLeft("Corruption") < 3 && IsCastingOK && Timers.SpellOkToCast("Corruption", 2000), true),

                    // Trying to fix the not facing target issue
                    new Decorator(ret=> !Me.IsMoving && !Me.Mounted && FpswareSettings.Instance.Warlock.CCControlledMovement.Contains("always") && Me.GotTarget && !Me.IsSafelyFacing(CT.Location),
                        new Action(context => CT.Face())),

                    // Life Tap
                    new Decorator(ret => !FpswareSettings.Instance.Warlock.DemoLifeTap.Contains("never") && Me.HealthPercent > FpswareSettings.Instance.Warlock.DemoLifeTapMinHealth && Me.ManaPercent < FpswareSettings.Instance.Warlock.DemoLifeTapMana,
                        new Sequence(
                            Spells.Cast("Life Tap"),
                            new WaitContinue(2, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                            )),


                    Spells.Cast("Health Funnel", ret => !Spells.HasSpell(108415) && Me.GotAlivePet && Me.Pet.HealthPercent < FpswareSettings.Instance.Warlock.DemoHealPetHealth && Me.Pet.Distance < 45 && SpellManager.HasSpell("Health Funnel") && !SpellManager.Spells["Health Funnel"].Cooldown),
                    // Soul Link is handled in our Rest logic, but there are a few times when we aggro and immediately enter combat, thereby skipping the application
                    // This is just a redundency check, after all this is a rather important spell
                    new Decorator(ret => FpswareSettings.Instance.Warlock.DemoSoulLink.Contains("always") && Me.GotAlivePet && !Me.Auras.ContainsKey("Soul Link") && WoWSpell.FromId(108415).CanCast,
                        new Action(r => Spells.Cast("Soul Link"))),

                    //
                    // ==============[ Metamorphosis ]==============
                    //
                    new Decorator(ret => StyxWoW.Me.GetCurrentPower(WoWPowerType.DemonicFury) >= FpswareSettings.Instance.Warlock.MetamorphosisMaxFury && CLC.ResultOK(FpswareSettings.Instance.Warlock.MetamorphosisWhen) && !Me.HasAura("Metamorphosis"),
                        new ProbabilitySelector( Spells.BuffSelf("Metamorphosis"))),

                    new Decorator(ret=> Me.HasAura("Metamorphosis"),
                        new PrioritySelector(
                            // As we're using LUA casting we need to do some range and LOS checks or it tries to cast when out of range or LOS
                            new Decorator(ret => CT.Distance >= 40, Movement.MoveToTarget(true, 36f)),
                            new Decorator(ret=> !CT.InLineOfSpellSight, Movement.MoveToLOS(ret=>CT)),

                            new Decorator(ret => Me.GetCurrentPower(WoWPowerType.DemonicFury) < FpswareSettings.Instance.Warlock.MetamorphosisMinFury && !Me.HasAura("Dark Soul: Knowledge"), new Action(r => Lua.DoString("CancelUnitBuff('player', 'Metamorphosis')"))),
                            new Decorator(ret => !Me.HasAura("Immolation Aura") && WoWSpell.FromId(104025).CanCast && CLC.CountOfMobs(FpswareSettings.Instance.Warlock.MetamorphosisImmolationAura,8,Me), new Action(r => Spells.LUACast("Immolation Aura"))),
                            
                            // Doom them all!!! MWAHAAAAAaaaaa.....
                            new Decorator(ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.MetamorphosisDoom) && AddsAndOthers.HasAdds && WoWSpell.FromId(124913).CanCast && DoTAddTarget("Doom") != null,
                                new Sequence(
                                    Spells.Buff("Corruption", ret => DoTAddTarget("Doom"), ret => IsCastingOK, true),
                                    new WaitContinue(2, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                                        )),

                            new Decorator(ret => !CT.HasMyAura("Doom") && IsCastingOK && WoWSpell.FromId(124913).CanCast && CLC.ResultOK(FpswareSettings.Instance.Warlock.MetamorphosisDoom), new Action(r => Spells.LUACast("Doom"))),

                            //new Decorator(ret => !FpswareSettings.Instance.Warlock.MetamorphosisImmolationAura.Contains("never") && IsCastingOK && CT.Distance > 10 && CT.Distance < 15, new Action(r => Spells.LUACast("Demonic Leap"))),
                            new Decorator(ret =>  WoWSpell.FromId(124917).CanCast && CLC.CountOfMobs(FpswareSettings.Instance.Warlock.MetamorphosisImmolationAura, 6, CT), new Action(r => Spells.LUACast("Chaos Wave"))),
                            new Decorator(ret => !Me.HasAura("Aura of the Elements") && WoWSpell.FromId(116202).CanCast && IsCastingOK, new Action(r => Spells.LUACast("Aura of the Elements"))),
                            
                            // Because the additional DPS boost of Metamorphosis will make this spell kick ass!
                            new Decorator(ret => IsCastingOK && Me.HasAura("Molten Core") && WoWSpell.FromId(6353).CanCast && CLC.ResultOK(FpswareSettings.Instance.Warlock.DemoSoulFire),
                                new Action(r=>Spells.LUACast("Soul Fire"))
                                ),
                            
                            // Finally just nuke it
                            new Decorator(ret => IsCastingOK && WoWSpell.FromId(112089).CanCast && CLC.ResultOK(FpswareSettings.Instance.Warlock.MetamorphosisTouchOfChaos),
                                new Action(r=>Spells.LUACast("Touch of Chaos"))
                                )
                     )),

                    //
                    // ==============[ Metamorphosis ]==============
                    //

                    // If we have adds and we're allowed to DoT them with Corruption then do it
                    new Decorator(ret => !FpswareSettings.Instance.Warlock.DemoCorruption.Contains("never") && FpswareSettings.Instance.Warlock.DemoCorruptionDOTAdds.Contains("always") && AddsAndOthers.HasAdds && DoTAddTarget("Corruption") != null,
                        new Sequence(
                            Spells.Buff("Corruption", ret => DoTAddTarget("Corruption"), ret => true, true),
                            new WaitContinue(2, ret => !SpellManager.GlobalCooldown, new ActionAlwaysSucceed())
                            )),

                    Spells.Cast("Hand of Gul'dan", ret=> CLC.ResultOK(FpswareSettings.Instance.Warlock.HandOfGuldan) && IsCastingOK && !Me.HasAura("Metamorphosis") && !CT.HasMyAura("Shadowflame") && Timers.SpellOkToCast("Hand of Gul'dan", 2000)),
                    Spells.Cast("Drain Life", ret => Me.HealthPercent <= FpswareSettings.Instance.Warlock.DemoDrainLifeHealth),
                    Spells.Cast("Soul Fire", ret => Me.HasAura("Molten Core") && CLC.ResultOK(FpswareSettings.Instance.Warlock.DemoSoulFire) && IsCastingOK),
                    Spells.Cast("Shadow Bolt", ret => IsCastingOK && CLC.ResultOK(FpswareSettings.Instance.Warlock.DemoShadowBolt)),
                    
                    // Fall through spell
                    Spells.Cast("Fel Flame", ret => CLC.ResultOK(FpswareSettings.Instance.Warlock.DemoFelFlame) && IsCastingOK),



                    new Decorator(ret => Me.IsCasting || Me.IsChanneling, new Action(context => RunStatus.Success)),
                    Movement.MoveToTarget(true, 36f),

                    new Decorator(ret=> (Me.GotAlivePet && Me.Pet.Combat || Me.Combat), new ActionAlwaysSucceed())
                    );
            }
        }

        public static Composite PullBehavior_Demonology
        {
            get
            {
                return new PrioritySelector(

                    Spells.WaitForCast(),
                    Misc.EnsureTarget(),
                    new Decorator(ret => Me.Mounted, new Action(context => Mount.Dismount())),
                    Movement.FaceTarget(),
                    Movement.ForceFacingTarget(),
                    Movement.MoveToLOS(),
                    Movement.Fixes(),

                    // Somehow we've got a target that is not hostile or attackable. Blacklist it and move on
                    new Decorator(ret => !CT.Attackable || CT.IsFriendly,
                        new Sequence(
                            new Action(context => Log.Write(Colours.InformativeColour, "Somehow we've got a target that is friendly or not attackable, blacklisting it and moving on.")),
                            new Action(context => Blacklist.Add(CT, TimeSpan.FromMinutes(1))),
                            new Action(context => Me.ClearTarget())
                        )),

                    new Decorator(ret => Me.GotAlivePet && Timers.SpellOkToCast("Pet Attack Pull", 2000) && ((Me.Pet.GotTarget && Me.Pet.CurrentTargetGuid != Me.CurrentTargetGuid) || !Me.Pet.GotTarget),
                        new Sequence(
                            new Action(delegate { Pets.CastPetAction("Attack"); }),
                            new Action(delegate { Timers.Reset("Pet Attack Pull");}),
                            new Action(ctx => RunStatus.Failure)
                            )),

                    // User defined pull options
                    new Decorator(ret => FpswareSettings.Instance.Warlock.DemoPull.Contains("user defined"),
                                  new PrioritySelector(

                                      Spells.Cast("Soul Fire", ret => SoulFireWithMoltenCore && FpswareSettings.Instance.Warlock.DemoPullSoulFire.Contains("always") && !Me.IsMoving),
                                      Spells.Cast("Hand of Gul'dan", ret =>  FpswareSettings.Instance.Warlock.DemoPullHandOfGuldan.Contains("always") && !Me.IsMoving),
                                      Spells.Cast("Corruption", ret =>  FpswareSettings.Instance.Warlock.DemoPullCorruption.Contains("always") && !Me.IsMoving),
                                      Spells.Cast("Shadow Bolt", ret =>  FpswareSettings.Instance.Warlock.DemoPullShadowBolt.Contains("always") && !Me.IsMoving)

                                      )),


                    // Automatic fall through stuff
                    new Decorator(ret => FpswareSettings.Instance.Warlock.DemoPull.Contains("automatic"),
                                  new PrioritySelector(

                                      Spells.Cast("Soul Fire", ret => SoulFireWithMoltenCore && !Me.IsMoving),
                                      Spells.Cast("Shadow Bolt", ret => !Me.IsMoving)

                                      )),


                    new Decorator(ret => Me.IsCasting || Me.IsChanneling, new Action(context => RunStatus.Success)),

                    Movement.PullApproach(),
                    Movement.MoveToTarget(true, 35f)
                    );
            }
        }
        
    }
}